import TRTC from "trtc-js-sdk";

const deviceFailAttention =
  "1. 若浏览器弹出提示，请选择“允许”<br>" +
  "2. 若杀毒软件弹出提示，请选择“允许”<br>" +
  "3. 检查系统设置，允许浏览器访问摄像头及麦克风<br>" +
  "4. 检查浏览器设置，允许网页访问摄像头及麦克风<br>" +
  "5. 检查摄像头/麦克风是否正确连接并开启<br>" +
  "6. 尝试重新连接摄像头/麦克风<br>" +
  "7. 尝试重启设备后重新检测";
const networkFailAttention =
  "1. 请检查设备是否联网<br>" +
  "2. 请刷新网页后再次检测<br>" +
  "3. 请尝试更换网络后再次检测";

const createLiveDeviceUtils = (options = {}) => {
  return LiveDeviceUtils.getInstance(options);
};

class LiveDeviceUtils {
  static instance = null;
  static getInstance(options) {
    if (LiveDeviceUtils.instance == null) {
      LiveDeviceUtils.instance = new LiveDeviceUtils(options);
    }
    return LiveDeviceUtils.instance;
  }

  constructor(options) {
    this.cameraList = [];
    this.micPhoneList = [];
    this.voiceList = [];
    this.options = options;
    this.deviceTesting = "FAIL";

    // safari和firefox浏览器上检测不到扬声器设备
    this.noVoiceDevice = isSafari() || isFirefox();

    this.hasNetworkConnect = false;
    this.reStartTesting = true;
    this.hasResult = false; //是否有结果
  }

  async init() {
    // await this.startDeviceConnect();
    await this.deviceInit();
  }

  get hasCameraDevice() {
    return this.cameraList.length > 0;
  }

  get hasMicDevice() {
    return this.micPhoneList.length > 0;
  }

  // safari和firefox浏览器上检测不到扬声器设备 设置为true
  get hasVoiceDevice() {
    return this.noVoiceDevice ? true : this.voiceList.length > 0;
  }

  get hasCameraConnect() {
    for (let camera of this.cameraList) {
      if (camera.deviceId.length > 0) {
        return true;
      }
    }
    return false;
  }

  get hasMicConnect() {
    for (let mic of this.micPhoneList) {
      if (mic.deviceId.length > 0) {
        return true;
      }
    }
    return false;
  }

  get hasVoiceConnect() {
    return this.hasVoiceDevice;
  }

  // 设备检测结果（包括麦克风检测，摄像头检测，扬声器检测，网络检测）
  get connectResult() {
    return (
      this.hasCameraConnect &&
      this.hasVoiceConnect &&
      this.hasMicConnect &&
      this.hasNetworkConnect
    );
  }

  /**
   * 返回设备连接信息
   */
  get deviceConnectInfo() {
    let connectInfo = "连接出错，请重试";
    let {
      hasCameraDevice,
      hasMicDevice,
      hasVoiceDevice,
      hasCameraConnect,
      hasMicConnect,
      hasNetworkConnect
    } = this;
    // 第一步：浏览器未检测到摄像头/麦克风/扬声器设备的提示
    if (!(hasCameraDevice && hasMicDevice && hasVoiceDevice)) {
      connectInfo = `未检测到${hasCameraDevice ? "" : "【摄像头】"}${
        hasVoiceDevice ? "" : "【扬声器】"
      }${hasMicDevice ? "" : "【麦克风】"}设备，请检查设备连接`;
      return {
        step: 1,
        connectInfo
      };
    }
    // 第二步：浏览器未拿到摄像头/麦克风权限的提示
    if (!(hasCameraConnect && hasMicConnect)) {
      connectInfo = hasNetworkConnect
        ? "请允许浏览器及网页访问摄像头/麦克风设备"
        : "请允许浏览器及网页访问摄像头/麦克风设备，并检查网络连接";
      // 显示设备连接失败引导
      // $('#connect-attention-container').show();
      // $('#connect-attention-info').html(deviceFailAttention);
      return {
        step: 2,
        connectInfo,
        deviceFailAttention
      };
    }
    // 第三步：浏览器检测未连接网络的提示
    if (!hasNetworkConnect) {
      connectInfo = "网络连接失败，请检查网络连接";
      // 显示设备连接失败引导
      // $('#connect-attention-container').show();
      // $('#connect-attention-info').html(networkFailAttention);
      return {
        step: 3,
        connectInfo,
        networkFailAttention
      };
    }
    return {
      step: 0,
      connectInfo
    };
  }

  /**
   * 初始化device init
   */
  async deviceInit() {
    //初次进入判断是否需要弹框检测 是否可以直播
    if (!localStorage.getItem("byt_device_testing")) {
      // localStorage.setItem("byt_device_testing", Date.now());
      this.startDeviceConnect();
    } else {
      await this.getDeviceinfo();
      this.callMediaDeviceDialog();
    }
  }
  /**
   * 如果有设备未连接，唤起请求弹窗
   */
  callMediaDeviceDialog() {
    let {
      hasCameraConnect,
      hasMicConnect,
      hasCameraDevice,
      hasMicDevice
    } = this;
    if (!(hasCameraConnect && hasMicConnect)) {
      navigator.mediaDevices
        .getUserMedia({ video: hasCameraDevice, audio: hasMicDevice })
        .then(async () => {
          if (hasCameraDevice) hasCameraConnect = true;
          if (hasMicDevice) hasMicConnect = true;
          // 更新首页popover的option list
          this.cameraList = await TRTC.getCameras();
          this.micPhoneList = await TRTC.getMicrophones();
          // 显示设备连接信息
          // showDeviceConnectInfo();
        })
        .catch(err => {
          console.log("getUserMedia err", err.name, err.message);
          this.handleGetUserMediaError(err);
        });
    }
    this.hasResult = true;
  }

  /**
   * 获取设备信息
   */
  async getDeviceinfo() {
    this.cameraList = await TRTC.getCameras();
    this.micPhoneList = await TRTC.getMicrophones();
    this.voiceList = await TRTC.getSpeakers();

    this.hasNetworkConnect = isFileProtocol
      ? navigator.onLine
      : await this.isOnline();
    this.deviceTesting = "SUCCESS";
  }

  async startDeviceConnect() {
    this.reStartTesting = true;
    this.hasResult = false;
    // 重新获取连接信息
    await this.getDeviceinfo();
    // let {
    //   hasCameraConnect,
    //   hasMicConnect,
    //   hasCameraDevice,
    //   hasMicDevice
    // } = this;
    await new Promise(reslove => {
      setTimeout(() => {
        this.reStartTesting = false;
        reslove();
      }, 1200);
    });
    this.callMediaDeviceDialog();
  }

  updateCameraDeviceList() {}

  updateVoiceDeviceList() {}

  updateMicDeviceList() {}

  /**
   * 监听设备变化
   */
  ondevicechange() {
    navigator.mediaDevices.ondevicechange = async function() {
      // 当前在摄像头检测页
      if (this.tab === "camera-testing-body") {
        await this.updateCameraDeviceList();
        return;
      }
      // 当前在扬声器检测页
      if (this.tab === "voice-testing-body") {
        await this.updateVoiceDeviceList();
        return;
      }
      // 当前在麦克风检测页
      if (this.tab === "mic-testing-body") {
        await this.updateMicDeviceList();
        return;
      }
    };
  }
  /**
   * 判断是否有网络连接
   */
  isOnline() {
    return new Promise(resolve => {
      try {
        let xhr = new XMLHttpRequest();
        xhr.onload = function() {
          resolve(true);
        };
        xhr.onerror = function() {
          resolve(false);
        };
        xhr.open("GET", "data/mock.json", true);
        xhr.send();
      } catch (err) {
        // console.log(err);
      }
    });
  }

  /**
   * 处理getUserMedia的错误
   * @param {Error} error
   */
  handleGetUserMediaError(error) {
    switch (error.name) {
      case "NotReadableError":
        // 当系统或浏览器异常的时候，可能会出现此错误，您可能需要引导用户重启电脑/浏览器来尝试恢复。
        alert(
          "暂时无法访问摄像头/麦克风，请确保系统授予当前浏览器摄像头/麦克风权限，并且没有其他应用占用摄像头/麦克风"
        );
        return;
      case "NotAllowedError":
        alert("用户/系统已拒绝授权访问摄像头或麦克风");
        return;
      case "NotFoundError":
        // 找不到摄像头或麦克风设备
        alert("找不到摄像头或麦克风设备");
        return;
      case "OverConstrainedError":
        alert(
          "采集属性设置错误，如果您指定了 cameraId/microphoneId，请确保它们是一个有效的非空字符串"
        );
        return;
      default:
        alert("初始化本地流时遇到未知错误, 请重试");
        return;
    }
  }

  async getCamera() {}

  async getMicPhone() {}
}

const isSafari = () => {
  return (
    /Safari/.test(navigator.userAgent) &&
    !/Chrome/.test(navigator.userAgent) &&
    !/CriOS/.test(navigator.userAgent) &&
    !/FxiOS/.test(navigator.userAgent) &&
    !/EdgiOS/.test(navigator.userAgent)
  );
};

const isFirefox = () => {
  return /Firefox/i.test(navigator.userAgent);
};

const isFileProtocol = () => {
  return location.protocol === "file:";
};

export default createLiveDeviceUtils();
